package gofire

import (
	"context"
	"fmt"
	"gofire/shutdown"
	"gofire/template"
	"net/http"
	"os"
	"os/signal"
	"time"
)

type Server interface {
	Run()
	NewGroup(prefix string) *Group
	Shutdown()
}

type HttpServer struct {
	*RouteRegistry
	addr        string
	middlewares []Middleware
	shutdown    *Shutdown
	template.TemplateEngine
}

func New(addr string, opts ...ServerOption) *HttpServer {
	router := newRouter()

	server := &HttpServer{
		RouteRegistry:  &RouteRegistry{router: router},
		addr:           addr,
		TemplateEngine: template.New(),
	}
	for _, opt := range opts {
		opt(server)
	}
	router.s = server
	return server
}

func (s *HttpServer) NewGroup(prefix string) *Group {
	return &Group{
		prefix:     prefix,
		server:     s,
		fullPrefix: prefix,
	}
}

func (s *HttpServer) Run() {
	err := http.ListenAndServe(s.addr, s.RouteRegistry)
	if err != nil {
		panic(err)
	}
}

func (s *HttpServer) Shutdown() {
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, shutdown.ShutdownSignals...)
	select {
	case sig := <-signals:
		fmt.Printf("get signal %s, application will shutdown \n", sig)
		ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
		defer cancel()
		if err := s.shutdown.Shutdown(ctx); err != nil {
			fmt.Println(err)
		}
		os.Exit(0)
	}
}
